Mise à jour le 05/12/2021
La commande rm de A à X

La commande rm de A à X

La commande rm ("remove") est une commande vitale qui permet de supprimer des fichiers ou des dossiers.

1. Pour supprimer un fichier

rm fichier.txt


2. Pour supprimer un dossier

2.1 Supprimer un dossier non vide (-r)

On peut procéder de deux manières :

rm -r dossier


💡️On peut également utiliser -R ou --recursive à la place de -r


2.2 Supprimer un dossier vide (-d)

Dans le cas où l'on souhaite supprimer un dossier vide, voici la commande que l'on peut effectuer :

rm -d dossier_vide


💡️On peut également utiliser la version longue --dir à la place de -d

💡️La commande rmdir existe également.


2.3 Astuce : supprimer un dossier contenant trop d'éléments

Dans le cas où un dossier contient beaucoup trop de fichiers, le rm ne fonctionne pas.

Voici le message qui s'afficherait sur un Debian anglais :

# cd dossier;
rm  *
# RETOUR : 
# -bash: /bin/rm: Argument list too long


On peut alors procéder de cette façon-là :

# cd dossier;
ls | xargs rm


💡️Voici une version assez agressive mais très efficace qui utilise les options -r et -f : `ls | xargs rm -rf`


En plus séquentiel, le code ci-dessus équivaudrait à ceci :

# cd dossier;
ls | while read param
do
  rm param
done


3. Supprimer plusieurs fichiers en une seule commande

Les arguments de rm peuvent être autant de noms de fichiers ou de chemins :

rm fichier_1 fichier_2;


4. Ignorer les fichiers inexistants (-f)

Contrairement à une idée répandue, l'option --force n'a d'effet que si l'un des fichiers en argument n'existe pas.

Par exemple, supposons que nous nous trouvons dans un répertoire où les fichiers fichier_1, fichier_3 et fichier_4 existent (fichier_2 n'existe donc pas).

Voici ce que donnerait l'utilisation du rm sans l'option --force :

# touch fichier_1  fichier_3 fichier_4
# denis@denis:/tmp/test $ ls
# fichier_1  fichier_3 fichier_4
rm fichier_1 fichier_2 fichier_3
# RETOUR :
# rm: impossible de supprimer 'fichier_2': Aucun fichier ou dossier de ce type
# $? vaut 1 : erreur
# Le ls retournera cela 
# fichier_4

Ici les fichiers 1 et 2 ont été supprimés mais le rm a retourné une erreur.
Ce comportement pourrait être problématique dans un script bash car le script pourrait s'arreter alors qu'il ne s'agit que d'une erreur mineure (ie. Le fichier fichier_2 est déjà supprimé).

Maintenant, le même exemple avec l'option --force (ou -f) :

# touch fichier_1  fichier_3 fichier_4
# denis@denis:/tmp/test $ ls
# fichier_1  fichier_3 fichier_4
rm -f fichier_1 fichier_2 fichier_3
# RETOUR : vide
# $? vaut 0 : ok
# Le ls retournera toujours cela
# fichier_4

Ici les fichiers 1 et 2 ont été supprimés sans que le rm retourne une erreur.

Ainsi, lorsque l'on cumule les options -f et -r, cela ne veut pas dire "forcer la suppression de tous les fichiers et répertoires", cela veut juste dire "supprime tous les fichiers et répertoire et ignore les fichiers qui n'existent pas".

Si l'on souhaite supprimer un fichier sans en avoir les droits d'écriture, le rm retournera une erreur, que l'option --force soit utilisée ou non. A la différence que la commande ne demande pas à l'utilisateur de confirmer son choix.

Résultat sans le --force :

rm /etc/sudoers
# RETOUR :
# rm: supprimer '/etc/sudoers' qui est protégé en écriture ? y
# rm: impossible de supprimer '/etc/sudoers': Permission non accordée
# $? vaut 1 : erreur


Résultat avec le --force :

rm -f /etc/sudoers
# RETOUR :
# rm: impossible de supprimer '/etc/sudoers': Permission non accordée
# $? vaut 1 : erreur

Ici encore, il parait pertinent d'utiliser l'option --force dans le cadre d'un script automatique qui ne demanderait pas à l'utilisateur de valider la suppression du fichier.
Cependant, il existe également l'option --interactive qui permet d'indiquer à la commande de façon explicite si l'on souhaite ou non que la commande pose des questions.

4.1 Demander à l'utilisateur de confirmer la suppression à chaque fichier (-i)

Si l'on souhaite que l'utilisateur valide chaque suppression, on peut utiliser l'option -i ou encore son équivalent verbeux --interactive=always

Voici un exemple :

touch fichier_1 fichier_2 fichier_3
rm -i fichier_*
# RETOUR : 
# rm : supprimer 'fichier_1' du type fichier vide ? n
# rm : supprimer 'fichier_2' du type fichier vide ? n
# rm : supprimer 'fichier_3' du type fichier vide ? n


Pour chaque fichier correspondant aux arguments, une confirmation est demandée à l'utilisateur.

Cette option peut avoir un intéret dans le cas où écrire les noms des fichiers à supprimer est fastidieux.

4.2 Combiner les options -r et -i

Si l'on combine les deux options -r et -i, le rm se comportera de cette façon :
- si le fichier à supprimer est un dossier, il demande à l'utilisateur s'il souhaite y rentrer
-- si l'utilisateur refuse : le dossier est conservé
-- si l'utilisateur accepte, le rm demande pour chaque fichier s'il doit être supprimé
-- lorsque tous les fichiers du dossier ont été parcourus, le programme demande si le dossier doit être supprimé
--- si l'utilisateur confirme la suppression et que le dossier n'est pas vide -> erreur
--- si l'utilisateur confirme la suppression et que le dossier est vide -> suppression du dossier
--- si l'utilisateur annule la suppression et que le dossier n'est pas vide -> pas de suppression

💣️Les options --interactive (-i, -I) n'ont aucun effet si l'option --force (-f) est présente.


5. Demander à l'utilisateur de confirmer une seule fois la suppression des fichiers (-I)

On peut utiliser l'option -I (ou --interactive=once) qui demande une seule fois à l'utilisateur de confirmer la suppression des fichiers.

La demande de confirmation s'effectue pour deux conditions :
- dans le cas où l'un des fichiers est un dossier
- dans le cas où le nombre des fichiers à supprimer dépasse scrictement 3

Donc :
- utiliser -I pour supprimer moins de 4 fichiers seuls n'aura pas d'effets

5.1 Exemple : le répertoire contient un dossier et plusieurs fichiers

Dans le cas où le répertoire contient au moins un dossier, on peut utiliser conjointement les options -r et -I.

touch fichier_1 fichier_2 fichier_3 fichier_4 && mkdir dossier;
rm -rI
# RETOUR : 
# rm : supprimer 5 arguments récursivement ? y


Si l'option -r n'est pas utilisée, le rm supprimera les fichiers mais retournera une erreur :

rm: impossible de supprimer 'dossier': est un dossier


6. Supprimer la racine / du disque (--no-preserve-root)

Il fut un temps où il était possible d'écrire "rm -rf /"qui avait pour effet de supprimer tous les fichiers du disque.

Si l'on souhaite tout de même le faire, il faut utiliser l'option --no-preserve-root de cette façon-ci :

rm -rf --no-preserve-root /


🧙‍♂️️Note : n'ayant pas de VM sous la main pour effectuer cette commande, je vous laisse découvrir son résultat ;-).


📖️️La sécurité sur le root existerait depuis 2006 sur les OS GNU : https://en.wikipedia.org/wiki/Rm_%28Unix%29#Protection_of_the_filesystem_root.


7. Eviter de supprimer les dossiers montés avec mount (--preserve-root)

Depuis 2018, il est possible d'utiliser l'option --preserve-root pour éviter de supprimer certains points de montage. Si l'option est utilisée, sa valeur vaut "all" par défaut.

8. Afficher la version de rm (--version)

Voici un exemple de sortie :

rm --version

rm (GNU coreutils) 8.28
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Paul Rubin, David MacKenzie, Richard M. Stallman,
and Jim Meyering


💣️Ne pas utiliser -v (équivalent à --verbose) pour afficher la version de rm.


9. Extrait du changelog de coreutils

Bien qu'assez vieille et stable, la commande rm est de temps en temps mise à jour.
Voici un extrait du changelog de coreutils(https://fossies.org/linux/coreutils/ChangeLog):

Member "coreutils-9.0/ChangeLog" (24 Sep 2021, 328480 Bytes) of package /linux/misc/coreutils-9.0.tar.xz:

1615 2020-11-26 Nishant Nayan <nishant.nayan@oracle.com>
1616
1617 rm: do not skip files upon failure to remove an empty dir
1618 When removing a directory fails for some reason, and that directory
1619 is empty, the rm_fts code gets the return value of the excise call
1620 confused with the return value of its earlier call to prompt,
1621 causing fts_skip_tree to be called again and the next file
1622 that rm would otherwise have deleted to survive.
1623
1624 * src/remove.c (rm_fts): Ensure we only skip a single fts entry,
1625 when processing empty dirs. I.e. only skip the entry
1626 having successfully removed it.
1627 * tests/rm/empty-immutable-skip.sh: New root-only test.
1628 * tests/local.mk: Add it.
1629 * NEWS: Mention the bug fix.
1630 Fixes https://bugs.gnu.org/44883

4310 2018-06-21 Pádraig Brady <P@draigBrady.com>
4311
4312 tests: provide an option to relax the need for gdb
4313 * tests/rm/r-root.sh: gdb provides extra protection,
4314 but is not strictly necessary. So provide an option
4315 for maintainers to relax the requirements.
4316
4317 rm: add --preserve-root=all to protect mounts
4318 * src/remove.c (rm_fts): With the --preserve-root=all extension,
4319 reject command line arguments that are mount points.
4320 * src/remove.h (rm_options): Add preserve_all_root to store config.
4321 * src/mv.c (rm_option_init): Init preserve_all_root to false.
4322 * src/rm.c (main): Init preserve_all_root as per option.
4323 (usage): Describe the new option.
4324 * src/remove.c (rm_fts): Lookup the parent device id,
4325 and reject the cli argument if a separate file system.
4326 * tests/rm/one-file-system.sh: Add a test case.
4327 * NEWS: Mention the new feature.

7692 2016-10-04 Pádraig Brady <P@draigBrady.com>
7693
7694 rm: disallow --n alias for --no-preserve-root
7695 * src/rm.c (main): Ensure the full --no-preserve-root
7696 option is specified, rather than allowing --n etc.
7697 * tests/rm/r-root.sh: Add a test case.
7698 * NEWS: Mention the change in behavior.
7699
7700 Improved by Jim Meyering.
7701 Fixes http://bugs.gnu.org/24604